﻿using Microsoft.AspNetCore.Http;
using SBlogCore.Common.FileUploadExtend;
using SBlogCore.WebAdminApplication.SysManager.IServices;
using SBlogCore.WebAdminApplication.SysManager.Dto;
using SBlogCore.Entitys.SystemManager;
using SBlogCore.Enums;
using SBlogCore.Common.Snowflake;
using SBlogCore.Common.DatabaseAccessor;
using Microsoft.Extensions.Options;
using SBlogCore.Common.App.Options;

namespace SBlogCore.WebAdminApplication.SysManager.Services
{
    public class SysFileInfoService: ISysFileInfoService
    {
        private readonly FileUploadFactory _saveFile;
        private readonly IRepository<SysFileInfo> _sysFileInfo;
        private readonly IRepository<SysFileMap> _sysFileMap;
        private readonly string? _host;

        public SysFileInfoService(
            FileUploadFactory saveFile
            ,IRepository<SysFileInfo> sysFileInfo
            , IRepository<SysFileMap> sysFileMap,
            IOptions<AppsettingsOptions> options
            )
        {
            this._saveFile = saveFile;
            this._sysFileInfo = sysFileInfo;
            this._sysFileMap = sysFileMap;
            this._host = options.Value.Host;
        }
        /// <summary>
        /// 保存任何文件
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        public async Task<List<SysFileInfoOutPut>> SaveAnyFile(List<IFormFile> files)
        {
            return await SaveFile(files);
        }
        /// <summary>
        /// 保存图片文件
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        public async Task<List<SysFileInfoOutPut>> SaveImageFile(List<IFormFile> files)
        {
            return await SaveFile(files,"image");
        }
        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="files"></param>
        /// <param name="fileType"></param>
        /// <returns></returns>
        private async Task<List<SysFileInfoOutPut>> SaveFile(List<IFormFile> files, string? fileType=null)
        {
            var paths = new List<SysFileInfoOutPut>();
            foreach (var file in files)
            {
                SysFileInfoOutPut outPut = new SysFileInfoOutPut();
                var upload = _saveFile.GetInstance(fileType);
                await upload.SaveAsync(file);
                var inPut = new SysFileInfoInPut
                {
                    FileLocation = (int) FileLocationEnum.Local,
                    FileOriginName = upload.Name,
                    FileType = fileType?? "any",
                    FileSuffix = file.ContentType,
                    FileSizeKb = upload.FileSize / 1024,
                    FileSizeInfo = $"{upload.FileSize / 1024 / 1024}M",
                    FileBucket = _host,
                    FilePath = upload.FilePath
                };
                var saveRes = await SaveFileInfo(inPut);
                outPut.WebPath = upload.WebPath;
                outPut.Id = saveRes.Id;
                paths.Add(outPut);
            }

            //返回保存文件的相对地址
            return paths;
        }

        /// <summary>
        /// 获取数据列表
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        public async Task<PageList<SysFileInfo>> GetList(SysFileInfoQueryInPut inPut)
        {
            var list = await _sysFileInfo.Where(w => true).Include(w => w.SysFileMap).ToPagedListAsync(inPut.PageIndex??1,inPut.PageSize??8);
            return list;
        }
        /// <summary>
        /// 获取文件映射信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<SysFileMap?> GetFileMapById(long id)
        {
            var data =await _sysFileMap.FirstOrDefaultAsync(w => w.Id == id);
            return data;
        }

        /// <summary>
        /// 保存数据与文件的映射关系
        /// </summary>
        /// <param name="dataId"></param>
        /// <param name="mapId"></param>
        /// <returns></returns>
        public async Task SaveFileMapToData<T>(long dataId,long mapId) where T : IBaseEntity
        {
            var key = typeof(T).Name;
            if (await _sysFileMap.AnyAsync(w => w.Key == key && w.DataId == dataId&&w.Id== mapId))
            {
                return;
            }
            var oldMap =await _sysFileMap.FirstOrDefaultAsync(w => w.Key == key && w.DataId == dataId);
            var map = await _sysFileMap.FirstOrDefaultAsync(w => w.Id == mapId);
            if (map != null)
            {
                map.DataId = dataId;
                map.Key = key;
                if (oldMap != null)
                {
                    oldMap.DataId = null;
                    oldMap.Key = null;
                    await _sysFileMap.UpdateAsync(oldMap);
                }
                
                await _sysFileMap.UpdateAsync(map);
            }
            if (map == null)
            {
                throw SBlogCoreException.Say($"映射关系不存在！");
            }
        }

        /// <summary>
        /// 保存文件信息
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        private async Task<SysFileMap> SaveFileInfo(SysFileInfoInPut inPut)
        {
            var res = inPut.Adapt<SysFileInfo>();
            res.Id= IDGenerator.NextId();
            //await _sysFileInfo.InsertNowAsync(res);
            var map=new SysFileMap
            {
                SysFileInfo = res
            };
            await _sysFileMap.InsertNowAsync(map);
            return map; 
        }
        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>

        public async Task DeleteFile(long id)
        {
            var fileInfo = await _sysFileInfo.Where(w => w.Id == id).FirstOrDefaultAsync();
            if (fileInfo == null)
            {
                throw SBlogCoreException.Say("文件数据不存在！");
            }
            var map = await _sysFileMap.Where(w => w.SysFileInfoId == fileInfo.Id).FirstOrDefaultAsync();
            if (map!=null)
            {
                await _sysFileMap.DeleteAsync(map);
            }
            _=DeleteFile(fileInfo.FilePath!);
        }


        /// <summary>
        /// 删除文件
        /// </summary>
        /// <returns></returns>
        private int DeleteFile(string path)
        {
            int res;
            var basePath = Directory.GetCurrentDirectory();
            var filePath = Path.Combine(basePath, path);
            if (!Directory.Exists(filePath))
                filePath = Path.Combine(basePath, @"/wwwroot", path);
            if (Directory.Exists(filePath))
            {
                Directory.Delete(filePath, true);
                res = 1;
            }
            else
            {
                res = 0;
            }
            return res;
        }
    }
}
